      1  /**

      2     A path in a maze is defined by a starting (row, column)

      3     position and a direction (NORTH, EAST, SOUTH, or WEST).

      4     A path starts out with the same starting and ending position

      5     and direction. It can be extended as the maze is traversed,

      6     until it reaches an exit, intersection, or dead end.

      7

      8     Intuitively, think of the path as starting at an intersection

      9     and then moving forward, potentially turning along the

     10     way, until it reaches another intersection.

     11  */

     12  public class Path

     13  {

     14     public static final int NORTH = 0;

     15     public static final int EAST = 1;

     16     public static final int SOUTH = 2;

     17     public static final int WEST = 3;

     18

     19     private static final int[] ROW_OFFSETS = { -1, 0, 1, 0 };

     20     private static final int[] COLUMN_OFFSETS = { 0, 1, 0, -1 };

     21

     22     private int startingRow;

     23     private int startingColumn;

     24     private int startingDirection;

     25     private int endingRow;

     26     private int endingColumn;

     27     private int endingDirection;

     28

     29     /**

     30        Constructs a path with a given position and direction

     31        @param row the starting row

     32        @param column the starting column

     33        @param direction the starting direction

     34     */

     35     public Path(int row, int column, int direction)

     36     {

     37        startingRow = row;

     38        startingColumn = column;

     39        startingDirection = direction;

     40        endingRow = row;

     41        endingColumn = column;

     42        endingDirection = direction;

     43     }

     44

     45     /**

     46        Moves the ending position of this path one unit in the

     47        current direction.

     48     */

     49     public void move()

     50     {

     51        endingRow = getNextRow();

     52        endingColumn = getNextColumn();

     53     }

     54

     55     /**

     56        Turns the ending direction of this path clockwise.

     57     */

     58     public void turn()

     59     {

     60        final int DIRECTIONS = 4;

     61        endingDirection = (endingDirection + 1) % DIRECTIONS;

     62     }

     63

     64     /**

     65        Gets the ending row of this path.

     66        @return the ending row

     67     */

     68     public int getEndingRow()

     69     {

     70        return endingRow;

     71     }

     72

     73     /**

     74        Gets the ending column of this path.

     75        @return the ending column

     76     */

     77     public int getEndingColumn()

     78     {

     79        return endingColumn;

     80     }

     81

     82     /**

     83        Gets the next row of this path if it continues in the ending

     84        direction.

     85        @return the next row

     86     */

     87     public int getNextRow()

     88     {

     89        return endingRow + ROW_OFFSETS[endingDirection];

     90     }

     91

     92     /**

     93        Gets the next column of this path if it continues in the ending

     94        direction.

     95        @return the next row

     96     */

     97     public int getNextColumn()

     98     {

     99        return endingColumn + COLUMN_OFFSETS[endingDirection];

    100     }

    101

    102     /**

    103        Checks whether two directions are opposites of each other.

    104        @param dir1 a direction between 0 and 3

    105        @param dir2 a direction between 0 and 3

    106        @return true if they are opposites (i.e. 0 and 2, 1 and 3,

    107        2 and 0, or 3 and 1)

    108     */

    109     private static boolean isOpposite(int dir1, int dir2)

    110     {

    111        return dir1 != dir2 && (dir1 + dir2) % 2 == 0;

    112     }

    113

    114     /**

    115        Checks whether this path is the opposite of another one.

    116        @param other another path that ends where this path starts

    117        @return true if other is the opposite of this path

    118     */

    119     public boolean isOpposite(Path other)

    120     {

    121        return startingRow == other.endingRow

    122           && startingColumn == other.endingColumn

    123           && isOpposite(startingDirection, other.endingDirection);

    124     }

    125

    126     public String toString()

    127     {

    128        String result = "(" + startingRow + "," + startingColumn

    129           + ")" + "NESW".charAt(startingDirection);

    130        if (endingRow != startingRow || endingColumn != startingColumn)

    131        {

    132  	  result = result + "<->(" + endingRow + "," + endingColumn

    133               + ")"+ "NESW".charAt(endingDirection);

    134        }

    135        return result;

    136     }

    137  }